<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <h1>寄生组合式继承</h1>
    <p>组合继承的一些不足之处可以用寄生组合式继承来解决。</p>
    <p>所谓寄生组合式继承，即<mark>通过借用构造函数来继承属性，通过原型链的混成形式来继承方法。</mark>其背后的基本思路是：不必为了指定子类型的原型而调用超类型的构造函数，我们所需要的无非就是超类型原型的一个副本而已。本质上，就是使用寄生式继承来继承超类型的原型，然后再将结果指定给子类型的原型。
    </p>
    <p>寄生组合式继承基本规避了其他继承的大部分缺点，应该比较强大了，也是平时使用最多的一种继承。</p>
    <p>可以用寄生组合继承实现ES6 Class extends，但是还是会有细微的差别</p>
</body>
<script>
    function Parent(name) {
        this.name = name;
        this.colors = ['red', 'blue', 'green'];
    }

    Parent.prototype.getName = function () {
        console.log(this.name)
    }

    function Child(name, age) {
        Parent.call(this, name);
        this.age = age;
    }

    // 原型式继承的方法
    function object(o) {
        function F() { }
        F.prototype = o;
        return new F();
        // 通过构造一个介于 Parent 与 Child 之间的对象，并使该对象的 prototype 属性指向 Parent 的 prototype对象，
        // 来避开通过调用 Parent 构造函数的方式来产生一个 prototype 指向Parent prototype对象的对象。
    }

    // 寄生组合继承
    function inheritPrototype(child, parent) {
        // 不直接child.prototype=parent.prototype呢？
        // 原因 : 当我们想给 Child 的prototype里面添加共享属性或者方法时，如果其 prototype 指向的是 Parent 的 prototype，那么在 Child 的 prototype 里添加的属性和方法也会反映在 Parent 的 prototype 里面，
        // 这明显是不合理的，这样做的后果是当我们只想使用 Parent 时，也能看见 Child 往里面扔的方法和属性。
        // 所以需要每个构造函数都需要持有自己专用的prototype对象
        var prototype = object(parent.prototype);
        prototype.constructor = child;
        child.prototype = prototype;
    }

    inheritPrototype(Child, Parent);

    var child1 = new Child('kevin', '18');

    console.log(child1);
</script>

</html>